package com.ruoyi.dingtalk.service.impl;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dingtalk.api.response.OapiDepartmentGetResponse;
import com.dingtalk.api.response.OapiDepartmentListResponse;
import com.dingtalk.api.response.OapiUserGetResponse;
import com.dingtalk.api.response.OapiUserSimplelistResponse;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.dingtalk.dao.DdDeptDao;
import com.ruoyi.dingtalk.domain.DdDept;
import com.ruoyi.dingtalk.domain.DdUser;
import com.ruoyi.dingtalk.mapper.DdDeptMapper;
import com.ruoyi.dingtalk.service.DdDeptService;
import com.ruoyi.dingtalk.service.DdUserService;
import com.ruoyi.dingtalk.service.DingTalkApiService;
import com.ruoyi.dingtalk.util.DingTalkUtil;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DdDeptServiceImpl extends ServiceImpl<DdDeptMapper, DdDept> implements DdDeptService {

    private DingTalkApiService dingTalkApiService;
    private DdDeptDao ddDeptDao;
    private ISysConfigService iSysConfigService;
    private ISysDeptService iSysDeptService;
    private DdUserService ddUserService;
    private ISysUserService iSysUserService;

    @Autowired
    public void setDingTalkApiService(DingTalkApiService dingTalkApiService) {
        this.dingTalkApiService = dingTalkApiService;
    }

    @Autowired
    public void setiSysUserService(ISysUserService iSysUserService) {
        this.iSysUserService = iSysUserService;
    }

    @Autowired
    public void setDdUserService(DdUserService ddUserService) {
        this.ddUserService = ddUserService;
    }

    @Autowired
    public void setiSysDeptService(ISysDeptService iSysDeptService) {
        this.iSysDeptService = iSysDeptService;
    }

    @Autowired
    public void setDdDeptDao(DdDeptDao ddDeptDao) {
        this.ddDeptDao = ddDeptDao;
    }

    @Autowired
    public void setiSysConfigService(ISysConfigService iSysConfigService) {
        this.iSysConfigService = iSysConfigService;
    }

    /**
     * 同步钉钉部门组织
     *
     * @param ddDeptId     钉钉部门用户
     * @param ddParentId   钉钉父部门
     * @param parentId     父部门
     * @param path         长路径 祖籍列表
     * @param initPassword 初始化密码
     * @param ddCorpId     钉钉企业id
     * @param appKey       钉钉应用appKey
     * @param appSecret    钉钉应用密钥
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void genDeptUser(Long ddDeptId, Long ddParentId, Long parentId, String path, String initPassword, String ddCorpId, String appKey, String appSecret) throws ApiException {
        //获取当前登录用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        //获取主节点的部门详情信息
        OapiDepartmentGetResponse rootDept = DingTalkUtil.getDeptByDeptId(Objects.toString(ddDeptId), dingTalkApiService.getAccessToken(appKey, appSecret));
        if (Objects.isNull(rootDept) || !rootDept.getErrcode().equals(0L)) {
            log.error("{}", Objects.nonNull(rootDept) ? rootDept.getErrmsg() : "");
            throw new ServiceException("同步错误,获取部门详情失败");
        }
        String rootDeptName = rootDept.getName();
        if ("智能问答数字员工".equals(rootDeptName)) {
            log.warn("虚拟的部门:{},跳过处理!", JSON.toJSONString(rootDept));
            return;
        }
        LambdaQueryWrapper<DdDept> ddDeptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        ddDeptLambdaQueryWrapper.eq(DdDept::getDeptId, ddDeptId);
        ddDeptLambdaQueryWrapper.eq(DdDept::getDdCorpId, ddCorpId);
        DdDept ddDept = baseMapper.selectOne(ddDeptLambdaQueryWrapper);
        SysDept sysDept;
        if (Objects.isNull(ddDept)) {
            //没有对应的部门 也就没有相对应的系统部门
            ddDept = new DdDept();
            ddDept.setCreateBy(loginUser.getUsername());
            ddDept.setCreateTime(new Date());

            // 系统部门
            sysDept = new SysDept();
            sysDept.setStatus("0");
            sysDept.setDelFlag("0");
            sysDept.setCreateBy(loginUser.getUsername());
            sysDept.setCreateTime(new Date());
        } else {
            sysDept = iSysDeptService.selectDeptById(ddDept.getSysDeptId());
            if (Objects.isNull(sysDept)) {
                throw new ServiceException("部门数据查询出错!");
            }
        }
        ddDept.setDeptId(ddDeptId);
        ddDept.setDeptName(rootDeptName);
        ddDept.setParentId(ddParentId);
        ddDept.setOrderInParent(rootDept.getOrder());

        //钉钉部门主管id列表
        String deptManagerUserids = rootDept.getDeptManagerUseridList();
        if (StringUtils.isNotBlank(deptManagerUserids)) {
            String[] deptManagerUseridsArray = deptManagerUserids.split("\\|");
            ddDept.setDeptManagerUserIds(Arrays.stream(deptManagerUseridsArray)
                    .filter(StringUtils::isNotBlank)
                    .collect(Collectors.joining(",")));
        }
        ddDept.setDdCorpId(ddCorpId);
        ddDept.setUpdateBy(loginUser.getUsername());
        ddDept.setUpdateTime(new Date());
        // 系统部门名称
        sysDept.setDeptName(ddDept.getDeptName());
        //系统部门 父部门id
        sysDept.setParentId(parentId);
        sysDept.setUpdateBy(loginUser.getUsername());
        sysDept.setUpdateTime(new Date());
        sysDept.setOrderNum(ddDept.getOrderInParent().intValue());
        // 保存或者更新系统部门
        iSysDeptService.saveOrUpdate(sysDept);
        Assert.notNull(sysDept.getDeptId(), () -> new ServiceException("系统部门主键不能为空!"));
        ddDept.setSysDeptId(sysDept.getDeptId());
        // 保存钉钉部门信息
        this.saveOrUpdate(ddDept);
        //部门id
        Long deptId = sysDept.getDeptId();

        path = path.concat(Objects.toString(deptId)).concat(".");
        //长路径
        sysDept.setAncestors(path);

        List<OapiUserSimplelistResponse.Userlist> userList;
        try {
            userList = DingTalkUtil.listUsersByDeptId(Objects.toString(ddDeptId), dingTalkApiService.getAccessToken(appKey, appSecret));
        } catch (ApiException e) {
            log.error("同步出现异常", e);
            throw new ServiceException("获取部门用户出现异常，同步失败!");
        }
        if (!userList.isEmpty()) {
            syncDingUser(initPassword, ddCorpId, loginUser, sysDept, userList, appKey, appSecret);
            String deptDirectorIds = rootDept.getDeptManagerUseridList();
            String deptLeadersName = StringUtils.EMPTY;
            String[] deptDirectorId = deptDirectorIds.split("\\|");
            if (deptDirectorId.length > 0) {
                String deptDirectorddUserId = deptDirectorId[0];
                if (StringUtils.isNotBlank(deptDirectorddUserId)) {
                    OapiUserSimplelistResponse.Userlist userlist = userList.parallelStream()
                            .filter(u -> StringUtils.equals(u.getUserid(), deptDirectorddUserId))
                            .findFirst().orElse(null);
                    if (Objects.nonNull(userlist)) {
                        deptLeadersName = userlist.getName();
                    }
                }
            }
            if (StringUtils.isNotBlank(deptLeadersName)) {
                sysDept.setLeader(deptLeadersName);
            }
        }

        iSysDeptService.saveOrUpdate(sysDept);
        //遍历子部门  重复操作
        List<OapiDepartmentListResponse.Department> departments;
        try {
            departments = DingTalkUtil.listDeptsByDeptId(Objects.toString(ddDeptId), dingTalkApiService.getAccessToken(appKey, appSecret));
        } catch (ApiException e) {
            throw new ServiceException("获取钉钉子部门出现异常");
        }
        for (OapiDepartmentListResponse.Department department : departments) {
            Long ddDeptId1 = department.getId();
            //ddDeptId就是父部门ID
            genDeptUser(ddDeptId1, ddDeptId, deptId, path, initPassword, ddCorpId, appKey, appSecret);
        }
    }

    /**
     * 同步钉钉用户信息
     *
     * @param initPassword 初始化密码
     * @param ddCorpId     钉钉部门id
     * @param loginUser    登录用户
     * @param sysDept      系统部门
     * @param userList     用户列表
     * @param appKey       钉钉应用key
     * @param appSecret    钉钉应用密钥
     * @throws ApiException API异常
     */
    private void syncDingUser(String initPassword, String ddCorpId, LoginUser loginUser, SysDept sysDept,
                              List<OapiUserSimplelistResponse.Userlist> userList, String appKey, String appSecret) throws ApiException {
        for (OapiUserSimplelistResponse.Userlist dUser : userList) {
            String name = dUser.getName();
            if ("数字员工".equals(name)) {
                log.warn("虚拟的数字员工:{}，跳过!", JSON.toJSONString(dUser));
                continue;
            }
            String ddUserId = dUser.getUserid();
            OapiUserGetResponse ddUserResponse = DingTalkUtil.getUserByUserId(ddUserId, dingTalkApiService.getAccessToken(appKey, appSecret));
            LambdaQueryWrapper<DdUser> ddUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
            ddUserLambdaQueryWrapper.eq(DdUser::getUserId, ddUserId);
            ddUserLambdaQueryWrapper.eq(DdUser::getDdCorpId, ddCorpId);
            DdUser ddUser = ddUserService.getOne(ddUserLambdaQueryWrapper);
            SysUser sysUser = null;
            if (Objects.isNull(ddUser)) {
                ddUser = new DdUser();
                ddUser.setCreateBy(loginUser.getUsername());
                ddUser.setCreateTime(new Date());
            } else {
                sysUser = iSysUserService.selectUserById(ddUser.getSysUserId());
                if (Objects.isNull(sysUser)) {
                    throw new ServiceException("查询系统用户信息失败!");
                }
            }
            if (Objects.isNull(sysUser)) {
                //创建一个新的系统部门信息
                sysUser = new SysUser();
                sysUser.setStatus("0");
                sysUser.setDelFlag("0");
                sysUser.setCreateBy(loginUser.getUsername());
                sysUser.setCreateTime(new Date());
            }
            ddUser.setUserId(ddUserId);
            ddUser.setDdCorpId(ddCorpId);
            ddUser.setDingTalkUserName(ddUserResponse.getName());
            ddUser.setManagerUserId(ddUserResponse.getManagerUserId());
            ddUser.setMobile(ddUserResponse.getMobile());
            ddUser.setJobNumber(ddUserResponse.getJobnumber());
            String email = ddUserResponse.getEmail();
            String orgEmail = ddUserResponse.getOrgEmail();
            if (StringUtils.isNotBlank(email)) {
                ddUser.setEmail(email);
            } else if (StringUtils.isNotBlank(orgEmail)) {
                ddUser.setEmail(orgEmail);
            }
            ddUser.setRemark(ddUserResponse.getRemark());
            ddUser.setOrgEmail(ddUserResponse.getOrgEmail());
            ddUser.setPosition(ddUserResponse.getPosition());
            ddUser.setUpdateTime(new Date());
            ddUser.setUpdateBy(loginUser.getUsername());
            // 系统用户
            sysUser.setDeptId(sysDept.getDeptId());
            String mobile = ddUser.getMobile();
            sysUser.setUserName(mobile);
            sysUser.setNickName(ddUser.getDingTalkUserName());
            sysUser.setEmail(ddUser.getEmail());
            sysUser.setPhonenumber(mobile);
            sysUser.setUpdateTime(new Date());
            sysUser.setUpdateBy(loginUser.getUsername());
            sysUser.setSex("2");
            sysUser.setPassword(SecurityUtils.encryptPassword(initPassword));
            boolean needInitRole = Objects.isNull(sysUser.getUserId());
            iSysUserService.saveOrUpdate(sysUser);
            if (needInitRole) {
                initUserRole(sysUser);
            }
            Assert.notNull(sysUser.getUserId(), () -> new ServiceException("系统用户主键不能为空!"));
            ddUser.setSysUserId(sysUser.getUserId());
            ddUserService.saveOrUpdate(ddUser);
            List<Long> department = ddUserResponse.getDepartment();
            if (department != null && !department.isEmpty()) {
                baseMapper.deleteUserDepartmentByuserId(ddUserId);
                for (Long deptId : department) {
                    baseMapper.insertUserDepartmentAssociation(ddUserId, deptId);
                }
            }
        }
    }

    private void initUserRole(SysUser sysUser) {
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(sysUser.getUserId());
        sysUserRole.setRoleId(2L);
        iSysUserService.genUserRole(sysUserRole);
    }


}
